package com.siyoumi.console.modules.sys.web;

import com.siyoumi.component.XApp;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.XRedisLock;
import com.siyoumi.config.SysConfig;
import com.siyoumi.console.config.CmdConfig;
import com.siyoumi.console.modules.sys.service.CmdApi;
import com.siyoumi.console.modules.sys.service.CmdThread;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import lombok.SneakyThrows;
import org.redisson.api.RDeque;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/app/console/api")
public class console_api
        extends ConsoleBase {
    @GetMapping("")
    public String index() {
        String html = XApp.getFileContent("view/console.html");
        html = html.replace("{#app_root}", SysConfig.getIns().getAppRoot())
                .replace("{#api_token}", input("token"));

        return html;
    }

    //输出命令key
    private final String redisKeyCmdMsg = "console";

    //执行命令
    @SneakyThrows
    @RequestMapping("/cmd")
    public XReturn cmd() {
        String type = input("type");
        if (XStr.isNullOrEmpty(type)) {
            return EnumSys.MISS_VAL.getR("miss type");
        }

        String[] scripts = CmdConfig.getIns().getScript().split(",");
        Integer scriptIndex = XStr.toInt(type, 0);
        if (scripts.length <= scriptIndex) {
            return XReturn.getR(10049, "type异常");
        }

        String cmd = scripts[scriptIndex];

        String key = "cmd:" + XApp.getStrID();
        //凭证，命令反馈用
        XRedis.getBean().setEx(key, "1", 60 * 10);

        XRedis.getBean().del(redisKeyCmdMsg); //先清空命令反馈
        CmdThread cmdThread = new CmdThread(redisKeyCmdMsg, cmd);

        cmdThread.start();
        while (cmdThread.isReady()) {
            Thread.sleep(100);
        }

        getR().setData("key", key);

        return getR();
    }

    //执行命令反馈
    @GetMapping("/cmd_msg")
    public XReturn cmdMsg() {
        String key = input("key");
        if (XStr.isNullOrEmpty(key)) {
            return EnumSys.MISS_VAL.getR("miss key");
        }

        if (!XRedis.getBean().exists(key)) {
            return EnumSys.ERR_VAL.getR("key error");
        }

        RDeque<String> deque = XRedis.getBean().getDeque(redisKeyCmdMsg);
        boolean done = false;

        List<String> msg = new ArrayList<>();
        while (true) {
            String val = deque.pollLast();
            if (val == null) {
                break;
            }
            if ("执行完成".equals(val)) {
                done = true;
            }

            msg.add(val);
        }

        if (done) {
            XRedis.getBean().del(key);
        }

        getR().setData("done", done);
        getR().setData("msg", msg);

        return getR();
    }

    @GetMapping("/test")
    public XReturn test() {
        getR().setData("cmd_script", CmdConfig.getIns().getScript());
        return getR();
    }


    @GetMapping("/run_cmd_siyoumi")
    public XReturn runCmdBySiyoumi() {
        //锁，防止两条语句并发执行
        String lockKey = "x|run_cmd_siyoumi";
        return XRedisLock.tryLockFunc(lockKey, k -> {
            XReturn r = CmdApi.getCmd();
            if (r.err()) {
                return r;
            }

            String id = r.getData("id");
            String cmd = r.getData("cmd");
            CmdApi.cmdRun(id); //标记开始执行

            CmdThread cmdThread = new CmdThread(id, cmd);
            cmdThread.start();

            while (!cmdThread.isReadFinish()) {
                //检查脚本是否已完成
                XApp.sleep(1);
            }

            RDeque<String> deque = XRedis.getBean().getDeque(id);
            List<String> msg = new ArrayList<>();
            while (true) {
                String val = deque.pollLast();
                if (val == null) {
                    break;
                }
                msg.add(val);
            }

            //删除，通知已完成
            XRedis.getBean().del(id);
            CmdApi.cmdDone(id, XJson.toJSONString(msg));

            //执行日志
            r.setData("msg", msg);
            return r;
        }, 10 * 60);
    }
}
